<?php

namespace addons\expressquery\library;

use think\Db;
use think\Exception;
use Throwable;

class Expressquery
{
    /**
     * 实现查询快递信息的钩子方法
     *
     * @param 类型 array 参数一的说明 [$express,$expresssn,$mobile]
     * @return array 返回类型
     * @example 示例  hook('get_express_list', [快递公司编码, 快递单号, 手机号])
     * @author Created by Xing <464401240@qq.com>
     */
    public function getExpressList($express, $expresssn, $mobile = '')
    {
        $list = ['code' => 0, 'msg' => '配置参数错误', 'data' => ''];
        if ($express && $expresssn) {
            $express_set = \app\admin\model\expressquery\ExpressqueryConfig::all();
            $express_set = $express_set[0];

            $express = $express == 'jymwl' ? 'jiayunmeiwuliu' : $express;
            $express = $express == 'TTKD' ? 'tiantian' : $express;
            $express = $express == 'jjwl' ? 'jiajiwuliu' : $express;
            $express = $express == 'zhongtiekuaiyun' ? 'ztky' : $express;

            if ($express_set['express_type'] == 'kuaidiniao') {
                $list = $this->getExpressBird($express, $expresssn, $express_set, $mobile);
            } elseif ($express_set['express_type'] == 'kuaidi100') {
                $list = $this->getExpressOneHundred($express, $expresssn, $express_set, $mobile);
            } else {
                if ($express_set['express_type'] == 'ali') {
                    $list = $this->getExpressAli($express, $expresssn, $express_set, $mobile);
                }
            }
        }
        return $list;
    }

    /**
     * 快递鸟
     * @param $express
     * @param $expresssn
     * @param string $mobile
     * @param $express_set
     * @return array|bool
     */
    private function getExpressBird($express, $expresssn, $express_set, $mobile = '')
    {
        if (empty($express_set['express_bird_userid']) || empty($express_set['express_bird_apikey'])) {
            return ['code' => 0, 'msg' => '配置参数错误', 'data' => ''];
        }

        if (!empty($express_set['express_bird_cache']) && 0 < $express_set['express_bird_cache']) {
            $cache_time = $express_set['express_bird_cache'] * 60;
            $cache = Db::name('expressquery_cache')->where(['express' => $express, 'expresssn' => $expresssn])->find();
            if (time() <= $cache['lasttime'] + $cache_time && !empty($cache['datas'])) {
                return ['code' => 1, 'msg' => '获取缓存数据成功', 'data' => json_decode($cache['datas'], true)];
            }
        }

        $url = 'http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx';
        $expressInfo = Db::name('expressquery')->where(['express' => $express])->find();

        if (empty($expressInfo)) {
            return ['code' => 0, 'msg' => '没有找到快递公司编码', 'data' => ''];
        }

        $expressEncoding = $expressInfo['coding'];
        $requestData = array('ShipperCode' => $expressEncoding, 'LogisticCode' => $expresssn);

        if ($expressEncoding == 'SF') {
            $cunstomername = substr($mobile, -4);
            $requestData['CustomerName'] = $cunstomername;
        }

        if ($expressEncoding == 'JGSD') {
            $requestData['CustomerName'] = $express_set['express_bird_customer_name'];
        }

        $requestData = json_encode($requestData);
        $datas = array(
            'EBusinessID' => $express_set['express_bird_userid'],
            'RequestType' => '1002',
            'RequestData' => urlencode($requestData),
            'DataType' => '2'
        );
        $datas['DataSign'] = urlencode(base64_encode(md5($requestData . $express_set['express_bird_apikey'])));
        $response = $this->httpPost($url, $datas);
        $expressData = json_decode($response, true);

        if ($expressData['Success'] == false) {
            //重试一次
            $datas = array(
                'EBusinessID' => $express_set['express_bird_userid'],
                'RequestType' => '8001',
                'RequestData' => urlencode($requestData),
                'DataType' => '2'
            );
            $datas['DataSign'] = urlencode(base64_encode(md5($requestData . $express_set['express_bird_apikey'])));
            $response = $this->httpPost($url, $datas);
            $expressData = json_decode($response, true);
        }

        $list = array();
        if (!empty($expressData['Traces']) && is_array($expressData['Traces'])) {
            foreach ($expressData['Traces'] as $index => $data) {
                $list[] = array('time' => trim($data['AcceptTime']), 'step' => trim($data['AcceptStation']));
            }
            $list = array_reverse($list);
        } else {
            return ['code' => 0, 'msg' => $expressData['Reason'], 'data' => $expressData];
        }

        if (0 < $express_set['express_bird_cache'] && !empty($list)) {
            if (empty($cache)) {
                Db::name('expressquery_cache')->insert(
                    [
                        'expresssn' => $expresssn,
                        'express'   => $express,
                        'lasttime'  => time(),
                        'datas'     => json_encode($list)
                    ]
                );
            } else {
                Db::name('expressquery_cache')->where(['id' => $cache['id']])->update(
                    [
                        'lasttime' => time(),
                        'datas'    => json_encode($list)
                    ]
                );
            }
        }

        return ['code' => 1, 'msg' => 'success', 'data' => $list];
    }

    /**
     * 快递100
     * @param $express
     * @param $expresssn
     * @param string $mobile
     * @param $express_set
     * @return array
     */
    private function getExpressOneHundred($express, $expresssn, $express_set, $mobile = '')
    {
        if (empty($express_set['apikey'])) {
            return ['code' => 0, 'msg' => '配置参数错误', 'data' => ''];
        }

        if (!empty($express_set['express_bird_cache']) && 0 < $express_set['express_bird_cache']) {
            $cache_time = $express_set['express_bird_cache'] * 60;
            $cache = Db::name('expressquery_cache')->where(['express' => $express, 'expresssn' => $expresssn])->find();
            if (time() <= $cache['lasttime'] + $cache_time && !empty($cache['datas'])) {
                return ['code' => 1, 'msg' => '获取缓存数据成功', 'data' => json_decode($cache['datas'], true)];
            }
        }

        $expressInfo = Db::name('expressquery')->where(['express' => $express])->find();
        if (empty($expressInfo)) {
            return ['code' => 0, 'msg' => '没有找到快递公司编码', 'data' => ''];
        }

        if ($express_set['kuaidi100_type'] == 'free') {
            $url = 'http://api.kuaidi100.com/api?id=' . $express_set['apikey'] . '&com=' . $express . '&num=' . $expresssn;
            $params = array();
        } else {
            $url = 'http://poll.kuaidi100.com/poll/query.do';
            $params = array(
                'customer' => $express_set['customer'],
                'param' => json_encode(array('com' => $express, 'num' => $expresssn))
            );
            $params['sign'] = md5($params['param'] . $express_set['apikey'] . $params['customer']);
            $params['sign'] = strtoupper($params['sign']);
            $params['phone'] = $mobile;
        }

        $content = $this->httpPost($url, $params);
        $info = json_decode($content, true);
        $info['request_url'] = $url;

        if (!isset($info) || empty($info['data']) || !is_array($info['data'])) {
            $useapi = false;
        } else {
            $useapi = true;
        }

        $list = array();
        if (!empty($info['data']) && is_array($info['data'])) {
            foreach ($info['data'] as $index => $data) {
                if ($data['context'] == '查无结果') {
                    continue;
                }
                $list[] = array('time' => trim($data['time']), 'step' => trim($data['context']));
            }
        } else {
            return ['code' => 0, 'msg' => $info['message'], 'data' => $info];
        }

        if ($useapi && 0 < $express_set['express_bird_cache'] && !empty($list)) {
            if (empty($cache)) {
                Db::name('expressquery_cache')->insert(
                    [
                        'expresssn' => $expresssn,
                        'express'   => $express,
                        'lasttime'  => time(),
                        'datas'     => json_encode($list)
                    ]
                );
            } else {
                Db::name('expressquery_cache')->where(['id' => $cache['id']])->update(
                    [
                        'lasttime' => time(),
                        'datas'    => json_encode($list)
                    ]
                );
            }
        }

        return ['code' => 1, 'msg' => 'success', 'data' => $list];
    }

    /**
     * 阿里云
     * @param $express
     * @param $expresssn
     * @param string $mobile
     * @param $express_set
     * @return array
     */
    private function getExpressAli($express, $expresssn, $express_set, $mobile = '')
    {
        $appcode = $express_set['aliappcode'];
        if (!$appcode) {
            return ['code' => 0, 'msg' => '配置参数错误', 'data' => ''];
        }
        //读取缓存数据
        if (!empty($express_set['express_bird_cache']) && 0 < $express_set['express_bird_cache']) {
            $cache_time = $express_set['express_bird_cache'] * 60;
            $cache = Db::name('expressquery_cache')->where(['express' => $express, 'expresssn' => $expresssn])->find();
            if ((time() <= ($cache['lasttime'] ?? 0) + $cache_time) && !empty($cache['datas'])) {
                return ['code' => 1, 'msg' => '获取缓存数据成功', 'data' => json_decode($cache['datas'], true)];
            }
        }

        $url = 'https://wdexpress.market.alicloudapi.com/gxali';
        $method = 'GET';
        $expressInfo = Db::name('expressquery')->where(['express' => $express])->find();
        if (empty($expressInfo)) {
            return ['code' => 0, 'msg' => '没有找到快递公司编码', 'data' => ''];
        }

        $expressEncoding = $expressInfo['coding'];
        $headers = array();
        array_push($headers, 'Authorization:APPCODE ' . $appcode);

        if ($expressEncoding == 'SF') {
            $cunstomername = substr($mobile, -4);
            $querys = 'n=' . $expresssn . ':' . $cunstomername . '&t=' . $expressEncoding;
        } else {
            $querys = 'n=' . $expresssn . '&t=' . $expressEncoding;
        }

        $querys = 'n=' . $expresssn;
        $url = $url . '?' . $querys;
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_FAILONERROR, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HEADER, false);
        //curl_setopt($curl, CURLOPT_HEADER, true); 如不输出json, 请打开这行代码，打印调试头部状态码。
        //状态码: 200 正常；400 URL无效；401 appCode错误； 403 次数用完； 500 API网管错误
        if (1 == strpos("$".$url, "https://")) {
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        }
        $out_put = curl_exec($curl);


        $expressData = json_decode($out_put, true);
        dump($expressData);
        $list = array();
        if (!empty($expressData['Traces']) && is_array($expressData['Traces'])) {
            foreach ($expressData['Traces'] as $index => $data) {
                $list[] = array('time' => trim($data['AcceptTime']), 'step' => trim($data['AcceptStation']));
            }
            $list = array_reverse($list);
        } else {
            $expressData['querys'] = $querys;
            return ['code' => 0, 'msg' => 'error', 'data' => $expressData];
        }

        if (0 < $express_set['express_bird_cache'] && !empty($list)) {
            if (empty($cache)) {
                Db::name('expressquery_cache')->insert(
                    [
                        'expresssn' => $expresssn,
                        'express'   => $express,
                        'lasttime'  => time(),
                        'datas'     => json_encode($list)
                    ]
                );
            } else {
                Db::name('expressquery_cache')->where(['id' => $cache['id']])->update(
                    [
                        'lasttime' => time(),
                        'datas'    => json_encode($list)
                    ]
                );
            }
        }

        return ['code' => 1, 'msg' => 'success', 'data' => $list];
    }


    /**
     * Post提交数据
     *
     * @param string $url 请求的Url
     * @param array $datas 提交的数据
     * @return string 响应返回的html
     * @author Created by Xing <464401240@qq.com>
     */
    private function httpPost($url, $datas)
    {
        $temps = array();
        foreach ($datas as $key => $value) {
            $temps[] = sprintf('%s=%s', $key, $value);
        }
        $post_data = implode('&', $temps);
        $url_info = parse_url($url);
        if (empty($url_info['port'])) {
            $url_info['port'] = 80;
        }
        $httpheader = "POST " . $url_info['path'] . " HTTP/1.0\r\n";
        $httpheader .= "Host:" . $url_info['host'] . "\r\n";
        $httpheader .= "Content-Type:application/x-www-form-urlencoded\r\n";
        $httpheader .= "Content-Length:" . strlen($post_data) . "\r\n";
        $httpheader .= "Connection:close\r\n\r\n";
        $httpheader .= $post_data;
        $fd = fsockopen($url_info['host'], $url_info['port']);
        fwrite($fd, $httpheader);
        $gets = "";
        while (!feof($fd)) {
            if (($header = @fgets($fd)) && ($header == "\r\n" || $header == "\n")) {
                break;
            }
        }
        while (!feof($fd)) {
            $gets .= fread($fd, 128);
        }
        fclose($fd);
        return $gets;
    }
}
